package com.wash.shoes.controller.dy.callblack;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.wash.shoes.common.enums.ChannelEnum;
import com.wash.shoes.common.enums.OrderStatusEnum;
import com.wash.shoes.domain.dto.BuyGoodsDto;
import com.wash.shoes.domain.dto.MobileOrderDto;
import com.wash.shoes.domain.dy.black.*;
import com.wash.shoes.domain.dy.request.DyRefundRequest;
import com.wash.shoes.domain.order.SaveOrderComponent;
import com.wash.shoes.entity.DyRefundPo;
import com.wash.shoes.entity.OrderPo;
import com.wash.shoes.exception.WashException;
import com.wash.shoes.resp.ShopAndFactoryPair;
import com.wash.shoes.service.CustomerService;
import com.wash.shoes.service.DyRefundService;
import com.wash.shoes.service.OrderGoodService;
import com.wash.shoes.service.OrderService;
import com.wash.shoes.util.CodeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * @author lijianguo
 * @Date 25/03/2025 13:16 请输入类的简介
 **/
@Api(tags = {"抖音-回调"})
@Log4j2
@RestController
@RequestMapping("common/dyCallBlack/")
public class DyCallBlackController {

    private final String dy_pay_key = "dyPay";
    @Resource
    SaveOrderComponent saveOrderComponent;
    @Resource
    OrderService orderService;
    @Resource
    OrderGoodService orderGoodService;
    @Resource
    DyRefundRequest dyRefundRequest;

    @Resource
    DyRefundService dyRefundService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @ApiOperation(value = "预下单回调扩展点", notes = "预约")
    @PostMapping("/preOrderCallbackExtensionNotify")
    @Transactional(rollbackFor = Exception.class)
    public HashMap<String, Object> preOrderCallbackExtensionNotify(@RequestBody DyMsgReturnDto dyMsgReturnDto) {

        CodeUtil.clearCurrentCacheCode();

        log.info("preOrderCallbackExtensionNotify entity {}", dyMsgReturnDto);
        log.info("===预下单回调扩展点===");
        log.info("preOrderCallbackExtensionNotify {}", JSONObject.toJSONString(dyMsgReturnDto));
        // 所有的请求的参数
        DyPreOrderDto dyPreOrderDto = JSONObject.parseObject(dyMsgReturnDto.getMsg(), DyPreOrderDto.class);
        // 订单的请求的参数
        MobileOrderDto mobileOrder = JSONObject.parseObject(dyPreOrderDto.getCp_extra(), MobileOrderDto.class);
        if (CollectionUtil.isEmpty(dyPreOrderDto.getSku_list())
                || Objects.isNull(dyPreOrderDto.getSku_list().get(0).getGoods_info())) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("err_no", 1);
            map.put("err_tips", "error");
            log.warn("preOrderCallbackExtensionNotify 获取抖音poid出错:{}", JSONUtil.toJsonStr(dyPreOrderDto.getSku_list()));
            return map;
        }
        String poid = mobileOrder.getPoid();
        String defaultPoid = "7477399071041259560";
        log.info("preOrderCallbackExtensionNotify 从order里面取出来的poid: {},默认的poid:{}", poid, defaultPoid);


        //转成预约时间,判断抖音预约时间不能早于当前时间
        if (Long.parseLong(mobileOrder.getShoeCollectionDate()) <= System.currentTimeMillis()) {
            throw new WashException("请选择正确的预约时间");
        }
        //获取商品的id
        String goodId = dyPreOrderDto.getSku_list().get(0).getGoods_info().getGoods_id();

        List<DyPreOrderDto.ItemOrderInfoList> itemOrderInfoLists = dyPreOrderDto.getItem_order_info_list();
        /* ShopPo shopPo = saveOrderComponent.getDyShopPo(poid,defaultPoid)*/
        ShopAndFactoryPair shopAndFactoryPair = saveOrderComponent.getShopPo(mobileOrder, ChannelEnum.DY.getCode(), goodId);
        Assert.notNull(shopAndFactoryPair, "抖音门店不存在,poid:" + poid + ",defaultPoid:" + defaultPoid);
        OrderPo orderPo = saveOrderComponent.process(mobileOrder, shopAndFactoryPair.getShopPo(), "D", goodId, itemOrderInfoLists);
        // 设置为抖音的订单来源
        orderPo.setComeFrom("3");
        // dy返回的订单号码
        orderPo.setMtOrderId(dyPreOrderDto.getOrder_id());
        orderPo.setMtUniOrderId(dyPreOrderDto.getOrder_id());
        orderPo.setMtSerialNumbers(dyPreOrderDto.getOrder_id());
        orderService.updateById(orderPo);

        HashMap<String, Object> map = new HashMap<>();
        map.put("err_no", 0);
        map.put("err_tips", "success");
        DyPreOrderVo dyPreOrderVo = new DyPreOrderVo();
        map.put("data", dyPreOrderVo);
        dyPreOrderVo.setOut_order_no(orderPo.getOrderNo());
        // 半个小时过期
        dyPreOrderVo.setPay_expire_seconds(30 * 60);

        DyPreOrderVo.OrderEntrySchema orderEntrySchema = new DyPreOrderVo.OrderEntrySchema();
        orderEntrySchema.setPath("pages/order/detail/detail?id=" + orderPo.getId());
        JSONObject params = new JSONObject();
        params.put("id", orderPo.getId());
        orderEntrySchema.setParams(params.toString());
        dyPreOrderVo.setOrder_entry_schema(orderEntrySchema);

        // 券的有效期
        List<DyPreOrderVo.OrderValidTime> orderValidTimeList = new ArrayList<>(mobileOrder.getShopGoodsInfo().size());
        for (BuyGoodsDto buyGoodsDto : mobileOrder.getShopGoodsInfo()) {
            DyPreOrderVo.OrderValidTime orderValidTime = new DyPreOrderVo.OrderValidTime();
            orderValidTime.setGoods_id(buyGoodsDto.getShopGoodsId());
            orderValidTimeList.add(orderValidTime);
        }
        dyPreOrderVo.setOrder_valid_time(orderValidTimeList);

        // 订单的商品相关信息
        List<DyPreOrderVo.OrderGoodsInfo> orderGoodsInfoList = new ArrayList<>(mobileOrder.getShopGoodsInfo().size());
        for (BuyGoodsDto buyGoodsDto : mobileOrder.getShopGoodsInfo()) {
            DyPreOrderVo.OrderGoodsInfo orderGoodsInfo = new DyPreOrderVo.OrderGoodsInfo();
            orderGoodsInfo.setGoods_id(buyGoodsDto.getShopGoodsId());
            orderGoodsInfoList.add(orderGoodsInfo);
        }

/*        List<OrderGoodPo> orderGoodPoList = orderGoodService.getOrderGoods(orderPo.getId());
        for (OrderGoodPo orderGoodPo : orderGoodPoList) {
            for (DyPreOrderDto.ItemOrderInfoList itemOrderInfoList : dyPreOrderDto.getItem_order_info_list()) {
                if (orderGoodPo.getGoodsId().equals(itemOrderInfoList.getGoods_id())) {
                    orderGoodPo.setItemOrderId(itemOrderInfoList.getItem_order_id());
                }
            }
        }
        orderGoodService.saveOrUpdateBatch(orderGoodPoList);TODO 这里放到process里面去处理的保存的ordergood的数据*/

        dyPreOrderVo.setOrder_goods_info(orderGoodsInfoList);
        dyPreOrderVo.setPay_notify_url("https://www.shoeswasher.com/prod-api/common/pay/notify");
        log.info("===预下单回调扩展点处理完成===  {}", JSONObject.toJSONString(dyPreOrderVo));
        // 保存数据在redis 订单是30分钟有效,这个key是60分钟
        redisTemplate.opsForValue().set(dy_pay_key, JSONObject.toJSONString(dyPreOrderVo), 60, TimeUnit.MINUTES);
        return map;
    }

    @ApiOperation("唤醒支付")
    @PostMapping("/wakeUpPayment")
    public HashMap<String, Object> wakeUpPayment(String orderId) {

        OrderPo orderPo = orderService.getById(orderId);
        if (orderPo == null) {
            throw new WashException("订单不存在");
        }
        if (!OrderStatusEnum.PRE_PAY.getStatus().equals(orderPo.getStatus())) {
            throw new WashException("订单的状态为: " + orderPo.getStatus());
        }

        String payKeyValue = redisTemplate.opsForValue().get(dy_pay_key);
        log.info("payKeyValue is {}", payKeyValue);

        DyPreOrderVo vo = JSONObject.parseObject(payKeyValue, DyPreOrderVo.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("err_no", 0);
        map.put("err_tips", "success");
        map.put("data", vo);
        // 重新唤醒支付
        return map;
    }

    @Autowired
    CustomerService customerService;

    @ApiOperation("退款的通知-订单在这里取消-这里会一致调用处理")
    @PostMapping("/dyRefundOrderNotify")
    public HashMap<String, Object> dyRefundOrderNotify(@RequestBody DyMsgReturnDto dyMsgReturnDto) throws InterruptedException {
        log.info("dyRefundOrderNotify entity {}", dyMsgReturnDto);
        log.info("===退款的通知====取消订单===");
        log.info("dyRefundOrderNotify {}", JSONObject.toJSONString(dyMsgReturnDto));
        HashMap<String, Object> map = new HashMap<>();
        RefundOrderBlackVo vo = new RefundOrderBlackVo();
        map.put("err_no", 0);
        map.put("err_tips", "success");
        map.put("data", vo);
        try {
            RefundOrderNotifyDto refundOrderNotifyDto =
                    JSONObject.parseObject(dyMsgReturnDto.getMsg(), RefundOrderNotifyDto.class);

            OrderPo orderPo = orderService.getByMtOrderId(refundOrderNotifyDto.getOrder_id());
            if ("pre_create_refund".equals(dyMsgReturnDto.getType()) &&
                    Objects.nonNull(refundOrderNotifyDto.getNeed_refund_audit()) && refundOrderNotifyDto.getNeed_refund_audit() == 1) {
                //需要审核就需要调用一下审核同意接口
                Executor executor = SpringUtils.getBean("asyncExecutor");
                executor.execute(() -> {
                    try {
                        //todo 抖音日志晚上
                        DyRefundPo dyRefundPo = JSONObject.parseObject(dyMsgReturnDto.getMsg(), DyRefundPo.class);
                        if (Objects.isNull(dyRefundPo)) {
                            dyRefundPo = new DyRefundPo();
                        }
                        dyRefundPo.setRefundText(dyMsgReturnDto.getMsg());
                        dyRefundPo.setJsonText(dyMsgReturnDto.getMsg());
                        dyRefundPo.setDyOrderId(orderPo.getMtOrderId());
                        dyRefundPo.setOrderId(orderPo.getId());
                        dyRefundPo.setOpenId(customerService.getById(orderPo.getCustomId()).getDyOpenId());
                        dyRefundPo.setOutOrderNo(orderPo.getOrderNo());
                        dyRefundPo.setRefundId(refundOrderNotifyDto.getRefund_id());
                        dyRefundPo.setAppId(refundOrderNotifyDto.getApp_id());
                        //todo 需要拿到是否需要审核，在通过审核去调用
                        dyRefundService.saveOrUpdate(dyRefundPo);
                        // 5s 以后执行
                        ThreadUtil.safeSleep(3000);
                        log.info("抖音订单退款需要审核===dyRefundRequest.audit==== {}", JSONObject.toJSONString(orderPo));
                        JSONObject jsonObject = dyRefundRequest.audit(orderPo);
                        log.info("抖音订单id:{},退款调用审核接口===dyRefundRequest.audit==== {}", orderPo.getId(), jsonObject.toString());
                    } catch (Exception e) {
                        log.error("订单开始退款===dyRefundRequest.refund==== orderid:" + orderPo.getId(), e);
                    }
                });
            }
            // 退款的回掉结果
            vo.setOut_refund_no(refundOrderNotifyDto.getOut_order_no());
            vo.getOrder_entry_schema().setPath("/pages/order/detail/detail?id=" + orderPo.getId());
            JSONObject params = new JSONObject();
            params.put("id", orderPo.getId());
            vo.getOrder_entry_schema().setParams(params.toString());
        } catch (Exception e) {
            log.error("dyRefundOrderNotify error," + "dyRefundOrderNotify entity {}", dyMsgReturnDto, e);
        }
        return map;

        // 0 元退款要处理一下
//        if ("pre_create_refund".equals(dyMsgReturnDto.getType())) {
//            // 退款的记录信息
//            DyRefundPo dyRefundPo = JSONObject.parseObject(dyMsgReturnDto.getMsg(), DyRefundPo.class);
//            dyRefundPo.setJsonText(dyMsgReturnDto.getMsg());
//            dyRefundPo.setDyOrderId(dyRefundPo.getOrderId());
//            dyRefundPo.setOrderId(orderPo.getId());
//            dyRefundService.saveOrUpdate(dyRefundPo);
//
//            Executo rexecutor = SpringUtils.getBean("asyncExecutor");
//            executor.execute(() -> {
//                // 5s 以后执行
//                ThreadUtil.safeSleep(5000);
//                log.info("订单开始退款===dyRefundRequest.refund==== {}", JSONObject.toJSONString(orderPo));
//                JSONObject refundJson = dyRefundRequest.refund(orderPo);
//                String errorCode = refundJson.getJSONObject("data").getString("error_code");
//                String description = refundJson.getJSONObject("data").getString("description");
//                dyRefundPo.setErrorCode(errorCode);
//                dyRefundPo.setRemark(description);
//                dyRefundPo.setRefundText(refundJson.toString());
//
//                if (errorCode.equals("0")) {
//                    dyRefundPo.setStatus(1);
//                } else {
//                    dyRefundPo.setStatus(2);
//                }
//                dyRefundService.saveOrUpdate(dyRefundPo);
//                log.info("订单退款结果 {}", refundJson);
//            });
//        }

    }

    @ApiOperation("退款结果通知地址")
    @PostMapping("/dyRefundOrderNotifyResult")
    public HashMap<String, Object> dyRefundOrderNotifyResult(@RequestBody Object dyMsgReturnDto) {

        log.info("dyRefundOrderNotifyResult entity {}", dyMsgReturnDto);
        log.info("===退款结果通知地址===");
        log.info("dyRefundOrderNotifyResult {}", JSONObject.toJSONString(dyMsgReturnDto));

        RefundOrderBlackVo vo = new RefundOrderBlackVo();
        HashMap<String, Object> map = new HashMap<>();
        map.put("err_no", 0);
        map.put("err_tips", "success");
        map.put("data", vo);
        // 退款结果通知地址
        return map;
    }

    @ApiOperation("预约消息通知能力-预约通知")
    @PostMapping("/preOrderCallbackReservationNotify")
    @Transactional(rollbackFor = Exception.class)
    public HashMap<String, Object> preOrderCallbackReservationNotify(@RequestBody DyMsgReturnDto dyMsgReturnDto) {

        log.info("preOrderCallbackReservationNotify entity {}", dyMsgReturnDto);
        log.info("===预约消息通知能力-预约通知===");
        log.info("preOrderCallbackReservationNotify {}", JSONObject.toJSONString(dyMsgReturnDto));

        HashMap<String, Object> map = new HashMap<>();
        map.put("err_no", 0);
        map.put("err_tips", "success");
        return map;
    }

}
